<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/3/22 0022
 * Time: 下午 16:53
 */
namespace  app\admin\controller;

use  \think\Db;
use think\Request;
use think\Session;
class cash extends Permissions
{
     /*
    配置参数
    */
    var $config = array(
        'appid' => "wxfff70773494b17e4",    /*微信开放平台上的应用id*/
        'mch_id' => "1501041251",   /*微信申请成功之后邮件中的商户id*/
        'api_key' => "RNFlJg20x2yGcF71kq2bNYRHBrNeGgdq",    /*在微信商户平台上自己设定的api密钥 32位*/
        'KEY_PEM'=>"../extend/pay/apiclient_key.pem",
        'CERT_PEM'=>"../extend/pay/apiclient_cert.pem",
    ); 

    /**
     * 管理员列表
     * @return [type] [description]
     */
    public function index()
    {
       
        $res = Session::get("admin_cate_id");
        $ress = Session::get("admin");
        $resa = Db::name('admin')->where('id',$ress)->value('name');
        $resb = Db::name('agent')->where('phone',$resa)->value('id');

        $model = Db::name('cash');
        $post = $this->request->param();
        if (isset($post['phone']) and !empty($post['phone'])) {
            $where['phone'] = ['like', '%' . $post['phone'] . '%'];
        }

        if($res==1){
            $agent = empty($where) ? $model->alias('a')->join('agent b','a.user_id=b.id')
                     ->field('money,reality_money,a.status,type,a.add_time,finish_time,a.last_money,phone,name,a.id')->order('add_time desc')
                     ->paginate(20) : $model->alias('a')->join('agent b','a.user_id=b.id')
                     ->field('money,reality_money,a.status,type,a.add_time,a.finish_time,a.last_money,phone,name,a.id')->where($where)->order('add_time desc')
                     ->paginate(20, false, ['query' => $this->request->param()]);

        }else{
            $agent = empty($where) ? $model->alias('a')->join('agent b','a.user_id=b.id')
                     ->field('money,reality_money,a.status,type,a.add_time,finish_time,a.last_money,phone,name,a.id')->where('user_id',$resb)->order('add_time desc')
                     ->paginate(20) : $model->alias('a')->join('agent b','a.user_id=b.id')
                     ->field('money,reality_money,a.status,type,a.add_time,a.finish_time,a.last_money,phone,name,a.id')->where($where)->where('user_id',$resb)
                     ->order('add_time desc')->paginate(20, false, ['query' => $this->request->param()]);
        }
        
        $this->assign('agent', $agent);
        return $this->fetch();
    }

    /**
     *提现未通过
     * 
     */
    public function update(Request $request){
        $id =$request->param('id',0,'intval');  
        if(!$id){
             return $this->error('缺少参数');
        }
        $dat['status']       = 2;
        $dat['finish_time']  = time();
        $lis = Db::name('cash')->where('id',$id)->update($dat);
        if($lis){
            $res  = Db::name('cash')->where('id',$id)->find();
            $list = Db::name('agent')->where('id',$res['user_id'])->setInc('last_money',$res['money']);
           if($list){
              return $this->success('拒绝成功','admin/cash/index');
           }
        }
   
    }



     /**
     *  作用：产生随机字符串，不长于32位
     */
    public function createNoncestr( $length = 32 )
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str ="";
        for ( $i = 0; $i < $length; $i++ )  {
            $str.= substr($chars, mt_rand(0, strlen($chars)-1), 1);
        }
        return $str;
    }

    /**
     *  作用：将xml转为array
     */
    public function xmlToArray($xml)
    {
        //将XML转为array
        $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $array_data;
    }

    /**
     * curl模拟get请求
     */
    protected function curlGet($url)
    {
        $curl = curl_init();
        //设置抓取的url
        curl_setopt($curl, CURLOPT_URL, $url);
        //设置头文件的信息作为数据流输出
        curl_setopt($curl, CURLOPT_HEADER, 0);
        //设置获取的信息以文件流的形式返回，而不是直接输出。
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);//绕过ssl验证
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        //执行命令
        $data = curl_exec($curl);
        return $data;
    }

    /**
     *  作用：以post方式提交xml到对应的接口url
     */
    public function postXmlCurl($data , $url , $second=30)
    {
        //初始化curl
        $ch = curl_init();
        //设置超时
        curl_setopt($ch, CURLOP_TIMEOUT, $second);
        //这里设置代理，如果有的话
        //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
        //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        curl_setopt($ch,CURLOPT_URL, $url);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
        //设置header
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        //post提交方式
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        //运行curl
        $data = curl_exec($ch);
        curl_close($ch);
        //返回结果
        if($data)
        {
            //curl_close($ch);
            return $data;
        }
        else
        {
            $error = curl_errno($ch);
            echo "curl出错，错误码:$error"."<br>";
            echo "<a href='http://curl.haxx.se/libcurl/c/libcurl-errors.html'>错误原因查询</a></br>";
            curl_close($ch);
            return false;
        }
    }

    /**
     *  作用：使用证书，以post方式提交xml到对应的接口url
     */
    protected function postXmlSSLCurl($xml,$url,$second=30)
    {
        $ch = curl_init();
        //超时时间
        curl_setopt($ch,CURLOPT_TIMEOUT,$second);
        //这里设置代理，如果有的话
        //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
        //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        curl_setopt($ch,CURLOPT_URL, $url);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
        //设置header
        curl_setopt($ch,CURLOPT_HEADER,FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,TRUE);
        //设置证书
        //使用证书：cert 与 key 分别属于两个.pem文件
        //默认格式为PEM，可以注释
        curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
        curl_setopt($ch,CURLOPT_SSLCERT, $this->config['CERT_PEM']);
        //默认格式为PEM，可以注释
        curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
        curl_setopt($ch,CURLOPT_SSLKEY, $this->config['KEY_PEM']);
        //post提交方式
        curl_setopt($ch,CURLOPT_POST, true);
        curl_setopt($ch,CURLOPT_POSTFIELDS,$xml);
        $data = curl_exec($ch);
        //返回结果
        if($data){
            curl_close($ch);
            return $data;
        }
        else {
            $error = curl_errno($ch);
            echo "curl出错，错误码:$error"."<br>";
            echo "<a href='http://curl.haxx.se/libcurl/c/libcurl-errors.html'>错误原因查询</a></br>";
            curl_close($ch);
            return false;
        }
    }

    /**
     *  作用：array转xml
     */
    private function arrayToXml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key=>$val) {
            if($val)
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
        }
        $xml .= "</xml>";
        return $xml;
    }

    /**
     *  作用：生成签名
     */
    private function getSign($Obj)
    {
        foreach ($Obj as $k => $v)
        {
            $Parameters[$k] = $v;
        }
        //签名步骤一：按字典序排序参数
        ksort($Parameters);
        $String = $this->formatBizQueryParaMap($Parameters, false);
        //echo '【string1】'.$String.'</br>';
        //签名步骤二：在string后加入KEY
        $String = $String."&key=" . $this->config['api_key'];
//        echo "【string2】".$String."</br>";
        //签名步骤三：MD5加密
        $String = md5($String);
        //echo "【string3】 ".$String."</br>";
        //签名步骤四：所有字符转为大写
        $result_ = strtoupper($String);
//        echo "【result】 ".$result_."</br>";exit;
        return $result_;
    }

    /**
     *  作用：格式化参数，签名过程需要使用
     */
    private function formatBizQueryParaMap($paraMap, $urlencode)
    {
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v)
        {
            if($urlencode)
            {
                $v = urlencode($v);
            }
            //$buff .= strtolower($k) . "=" . $v . "&";
            $buff .= $k . "=" . $v . "&";
        }
        $reqPar;
        if (strlen($buff) > 0)
        {
            $reqPar = substr($buff, 0, strlen($buff)-1);
        }
        return $reqPar;
    }

   


    /**
     *  企业付款到零钱
     */
    public function through()
    {
        $id = input('id');
        if(empty($id)){
           return $this->error('缺少参数');  
        }
        $order = build_order_no();
        $lis  = Db::name('cash')->where('id',$id)->find();

        $pay_nums          =   $lis['reality_money'];
        $redpack           =    Db::name('money_log');
        //查看用户绑定的微信公众号的openid
        $openid_info    =   Db::name('agent')->where(['id' => $lis['user_id']])->find();
        if(empty($openid_info) || !$openid_info['openid']){
             return $this->error("请先关注公众号绑定账户",'admin/cash/index');
        }
       
        /**
         * 首先记录发送零钱记录，发送成功后修改记录状态
         */
        $red_log['agent_id']        =   $lis['user_id'];
        $red_log['openid']          =   $openid_info['openid'];     //
        $red_log['appid']           =   $this->config['appid'];
        $red_log['mch_id']          =    $this->config['mch_id'];
        $red_log['mch_billno']     =    $order;
        $red_log['total_amount']   =   $pay_nums;
        $red_log['ip_address']     =   get_client_ip();
        $red_log['cash_time']      =   time();
        $red_log['status']     =  0;

        $result_id      =   $redpack->insert($red_log);
//            dump($result_id);exit;
        if($result_id == false){
            $this->error('红包发送失败');
        }

        /**
         *必填参数
         * mch_appid(商户账号)    mchid(商户号)   nonce_str(随机字符串)   sign(签名)    partner_trade_no(商户订单号)
         *openid(用户openid)      check_name(检验用户姓名选项[NO_CHECK , FORCE_CHECK])
         *amount(金额)    desc(付款描述)  spbill_create_ip(IP地址)
         *
         * 选填参数
         * device_info(设备号) re_user_name(收款用户姓名)
         */
        $transfers_url  =   'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';
    
        $params['mch_appid']     =   "wxfff70773494b17e4";
        $params['mchid']          =  "1501041251";
        $params['nonce_str']     =   $this->createNoncestr();
        $params['partner_trade_no']     = $order;
        $params['openid']                =   $openid_info['openid'];
        $params['check_name']           =   'NO_CHECK';
        $params['amount']               =   floor($pay_nums);
        $params['desc']                 =   '返利红包';
        $params['spbill_create_ip']   =   get_client_ip();
        $params['sign']         =   $this->getSign($params);
        //生成xml格式
        $xml    =   $this->arrayToXml($params);
        $result = $this->xmlToArray($this->postXmlSSLCurl($xml, $transfers_url));

        if($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS'){
            /**
             * 修改红包记录微信单号以及状态
             */
            $ids = Db::name('money_log')->where('agent_id',$lis['user_id'])->where('status',0)->value('id');
            $update_log['send_listid']      =   $result['payment_no'];      //微信订单号
            $update_log['cash_time']       =    strtotime($result['payment_time']);
            $update_log['status']           =  1;
            $redpack->where('id',$ids)->update($update_log);

            //修改审核状态
           
            $income['finish_time'] =   time();
            $income['status']     =  0;
            Db::name('cash')->where(['id' => $id])->update($income);

           
        }elseif($result['result_code'] == 'FAIL' && $result['err_code'] == 'SYSTEMERROR'){          //出现系统错误的情况下，需要重新查询付款状态，不然可能重复发送

            $get_transfer_url   =   'https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo';

            $query['appid']             =   $this->config['appid'];
            $query['mchid']             =   $this->config['mch_id'];
            $query['nonce_str']         =   $this->createNoncestr();
            $query['partner_trade_no'] =    $params['partner_trade_no'];
            $query['sign']              =    $this->getSign($query);

            //生成xml格式
            $xml    =   $this->arrayToXml($params);
            //请求查询结果
            $query_result = $this->xmlToArray($this->postXmlSSLCurl($xml, $get_transfer_url));

            if($query_result['return_code'] == 'SUCCESS' && $query_result['result_code'] == 'SUCCESS'){
                //如果请求结果的转账状态是成功的话，使用原订单号重新请求一遍
                if($query_result['status'] == 'SUCCESS'){
                    $this->sendTransfers($agent_withdrawals , $adminId ,  $query['partner_trade_no']);
                }
            }

        }else{
            $update_log['status']           =   0;
            $redpack->where(['id' => $result_id])->insert($update_log);
            $this->error($result['err_code_des']);
        }
    }

   
}